BeliefUpdates:

		{true}
	UpdateProperties([Width,Height,NrAgents,TeamName,Placement])
		{width(Width),height(Height),nrAgents(NrAgents),teamName(TeamName),placement(Placement),propertiesLoaded}
	
		{true}
	ActivatedMessageReceived(X,Y,BodyType,Rank)
		{activatedMessage(X,Y,BodyType,Rank),rank(Rank)}
		
		{phase(waitForActivation)} 
	Entered(X,Y,BodyType) 
		{not phase(waitForActivation),position(X,Y),bodyType(BodyType), entered, phase(waitForGameStart)}
	
	
		{round(Round)}
	Shot(X,Y,TargetName,TargetTeam,TargetBodyType)
		{shot(X,Y,TargetName,TargetTeam,TargetBodyType),not round(Round), round(Round+1)}
		
		{round(Round)}
	NoShot()
		{not round(Round), round(Round+1)}
		
	
		{shot(X,Y,TargetName,TargetTeam,TargetBodyType)}
	RemoveShot(X,Y,TargetName,TargetTeam,TargetBodyType)
		{not shot(X,Y,TargetName,TargetTeam,TargetBodyType)}
	

		{phase(move)}	
	Moved()
		{not phase(move), phase(waitForSenseMove)}

/*		
		{phase(Phase)}
	Moved()				// empty update to prevent deadlock
		{phase(Phase), phase(waitForSenseMoved), phase(shoot)}
*/
	
		//{phase(informShootPlan)}
		{phase(Phase)}
	InformedShoot()
		{not phase(Phase), phase(shoot)}
		
		{phase(shoot)}
	Shooted()
		{not phase(shoot), phase(waitForSenseShoot)}
		
		{phase(Phase)}
	Shooted()				// empty update to prevent deadlock
		{phase(Phase), phase(waitForSenseShoot), phase(move)}
	
//		{not inShootRange(X,Y) }
//	InShootRange(X,Y)
//		{ inShootRange(X,Y) }
		
		{ position(X,Y) and shootRange(S) }	
	AdjustShootRange()
		{ not something(S) }
		
		
		{phase(waitForSenseMove) and position(Xold, Yold)}
	Sensed(afterMove,X,Y)
		{not phase(waitForSenseMove), phase(shoot), not position(Xold,Yold), position(X,Y) }
		
		{phase(waitForSenseShoot) and position(Xold, Yold )}
	Sensed(afterShoot,X,Y)
		{not phase(waitForSenseShoot), phase(move), not position(Xold,Yold), position(X,Y) }
				
		{phase(Phase)}
	SetPhase(move)
		{not phase(Phase), phase(move)}
		
		{phase(Phase)}
	SetPhase(shoot)
		{not phase(Phase), phase(shoot)}
		
		{phase(X)}
	SetPhase(Y)
		{not phase(X), phase(Y)}
		
		{true}
	SetPhase(move)
		{phase(move)}
		
		{true}
	SetPhase(shoot)
		{phase(shoot)}
		
	
		
		{phase(X)}
	Died()
		{not phase(X), phase(terminated)}
		
		{phase(waitForGameStart)}
	GameStarted()
		{not phase(waitForGameStart), phase(move)}
		
		{}
	InformShootPlanReceived(Round,TeamMate,X,Y,Rank,Damage, TargetName, TargetTeam, TargetType)
		{informShootPlanReceived(Round,TeamMate,X,Y,Rank,Damage, TargetName, TargetTeam, TargetType)}
	/*
		{informShootPlanReceived(TeamMate,X,Y,Rank,Damage)}
	RemoveShootPlanMessage(TeamMate,X,Y,Rank,Damage)
		{not informShootPlanReceived(TeamMate,X,Y,Rank,Damage)}
	*/
	
	/*
		{}
	InformShootPlanSend(TeamMembers)
		{informShootPlanSend(TeamMembers)}
	*/	
		{}
	TotalDamageForShot(X,Y,TotalDamage)
		{totalDamageForShot(X,Y,TotalDamage)}
		
		
		
		
		
		
		
		
Beliefs:

	prob(P) :- is(X, rand), X < P.
//	add(X,Y,Z) :- is(Z,X+Y).
	
	/* Retrieve the damage for targetBodytype*/
	getDamage(scissor, 3) :- bodyType(rock).
	getDamage(rock, 3)	:- bodyType(paper).
	getDamage(paper, 3) :- bodyType(scissor).
	getDamage(_, 1 ).
//	getDamage(_, 1) :- bodyType(_).
	
	getTotalDamage([],Rank,Result) :- is(Result,0).
	
	getTotalDamage([shot(RankThem,Damage, TargetName, TargetTeam, TargetType)|Rest],Rank,Result) :- 
		Rank>RankThem, 
		getTotalDamage(Rest,Rank,Result2),
		is(Result,Result2+Damage).
		
	getTotalDamage([shot(RankThem,Damage, TargetName, TargetTeam, TargetType)|Rest],Rank,Result) :-
		Rank<RankThem,
		getTotalDamage(Rest,Rank,Result).	  
	
//	abs( 0, X ) :- is(X, 0).
	abs2( 0, 0 ).
	abs2( X, Y) :- X > 0, Y is (0+X). //is(Y, X). //Y is (0 + X).
	abs2( X, Y) :- X < 0, Y is (0-X). //is( Y, 0-X). //Y is (0-X).
	
	
	inShootRange( Xto, Yto ) :- 
			position( Xself, Yself ), shootRange( S ), 
			abs2( Xself-Xto, Xabs ),	abs2( Yself-Yto, Yabs ),
			Xtimes is (Xabs*Xabs),
			Ytimes is (Yabs*Yabs),
			Stimes is (S*S),
			Stimes = Xtimes+Ytimes.
	inShootRange( Xto, Yto ) :- 
			position( Xself, Yself ), shootRange( S ), 
			abs2( Xself-Xto, Xabs ),	abs2( Yself-Yto, Yabs ), 
			Xtimes is (Xabs*Xabs),
			Ytimes is (Yabs*Yabs),
			Stimes is (S*S),
			Stimes > Xtimes+Ytimes.
	
	distanceFromGroup(MaxMinValue,north,0) :- position(X,Y), MaxMinValue > Y.		
	distanceFromGroup(MaxMinValue,north,DistanceFromGroup) :- position(X,Y), is(DistanceFromGroupMinusOne,Y-MaxMinValue), is(DistanceFromGroup,DistanceFromGroupMinusOne+1).
	distanceFromGroup(MaxMinValue,south,0) :- position(X,Y), Y > MaxMinValue.	
	distanceFromGroup(MaxMinValue,south,DistanceFromGroup) :- position(X,Y), is(DistanceFromGroupMinusOne,MaxMinValue-Y), is(DistanceFromGroup,DistanceFromGroupMinusOne+1).
	distanceFromGroup(MaxMinValue,east,0) :- position(X,Y), MaxMinValue > X.	
	distanceFromGroup(MaxMinValue,east,DistanceFromGroup) :- position(X,Y), is(DistanceFromGroupMinusOne,X-MaxMinValue), is(DistanceFromGroup,DistanceFromGroupMinusOne+1).
	distanceFromGroup(MaxMinValue,west,0) :- position(X,Y), X > MaxMinValue.	
	distanceFromGroup(MaxMinValue,west,DistanceFromGroup) :- position(X,Y), is(DistanceFromGroupMinusOne,MaxMinValue-X), is(DistanceFromGroup,DistanceFromGroupMinusOne+1).
	
	
	round(0).
//	state(alive).
	managerAgent(manager).
	phase(waitForActivation).
	shootRange(4).
	maxDistanceFromGroup(2).
	moveOpositePlacementRounds(4).
	
	
	
Goals:
	propertiesLoaded
//	inShootRange(9,9)
//	alive
	
	
PG-rules:
	
	propertiesLoaded <- true |
	{
		@competition( getProperties(), ActionResult);
		B( ActionResult = [actionresult( Properties )] );
		adopta(entered);
		UpdateProperties(Properties)
	}
	
	entered <- activatedMessage(X,Y,BodyType,_) and width(Width) and height(Height) and nrAgents(NrAgents) and teamName(Teamname) and placement(Placement) |
	{
		@competition( enter(X,Y,BodyType, Width, Height, NrAgents, Teamname, Placement), _);
		//adopta(inShootRange(9,9));
		//adopta(randomMove());
		Entered(X,Y,BodyType)
	}
	
	
	// In walk phase, walk to weakest enemy.
	// Possible addition: ask list of most dangerous enemies from Env, and walk away from them
	true <- phase(move) and position(X,Y) and bodyType(BodyType) |
	{
		//randomMove()
		@competition( getEnemies(), Result );
		B( Result = [actionresult( Enemies )] );
		walkToWeakest( Enemies )		
	}
	
	
	
	true <- phase(shoot) and round(Round)|
	{
		/* Retrieves the team members within sense range*/
		@competition(getTeamMembers(),ActionResult1);
		B( ActionResult1 = [actionresult( TeamMembers)]);
		
		/* Retrieves the enemies within shooting range*/
		@competition(getEnemiesInShootingRange(),ActionResult2);
		B( ActionResult2 = [actionresult( EnemiesInShootRange)] );
	
		/* Informs other agents about a potential target */
		print( informShootPlan( TeamMembers, EniemiesInShootRange ) );
		informShootPlan(TeamMembers, EnemiesInShootRange);
				
		/* Waits n skips, for other informShootPlanMessages to arrive*/
		wait(3);
		
		determineShot(EnemiesInShootRange);
		
		/*registers the inform shoot plans with the logical environment.*/
		/* It is wrapped in a list, because aplFunctions inside a list, cannot be accepted from or to the environment*/
	    B(findall([X,Y,Damage, TargetName, TargetTeam, TargetType],informShootPlanReceived(Round,TeamMember,X,Y,Rank,Damage, TargetName, TargetTeam, TargetType),Shots));
		print(shotsPlans(Shots));
		@competition(registerShots(Shots),_);
		
		SetPhase(waitForSenseShoot);
		
		
		/* adopts goals that nan be performed in the move phase if needed*/
		adopta(clearShootInfo)
		//adopta(informShot(TeamMembers)) //takes too much time sometimes up to two seconds??/.
	}
	
	clearShootInfo <- not phase(shoot) |
	{
		removeShotInfo();
		dropgoal(clearShootInfo)
	}
	
	informShot(TeamMembers, X, Y, TargetName, TargetTeam, TargetBodyType) <- true |
	{
		B(getDamage(TargetBodyType,Damage));
		sendShot(TeamMembers, X,Y,Damage,TargetName, TargetTeam, TargetBodyType);
		dropgoal(informShot(TeamMembers, X, Y, TargetName, TargetTeam, TargetBodyType))
	}	

	
PC-rules:	

	randomMove() <- phase(move) and prob(0.25) and not position(X, Height-1 ) and width(Height)   |
	{
		move( north )
	}
	randomMove() <- phase(move) and prob(0.5)  and not position(Width-1, Y ) and width(Width)   |
	{
		move( east )
	}
	randomMove() <- phase(move) and prob(0.75)  and not position(X, 0 ) |
	{
		move( south )
	}
	randomMove() <- phase(move) and not position(0, Y ) |
	{
		move( west )
	}
	randomMove() <- phase(move) |
	{
		randomMove()
	}
	
	
	move( north ) <- phase( move ) and position(X,Y) and maxDistanceFromGroup(MaxDistanceFromGroup)|
	{
		
		@competition(getMaxYOfTeamMates(), ActionResult );
		B( ActionResult = [actionresult( [MaxY]  )]);
		
		print(maxY(MaxY));
		
		if B(MaxY > 0 and distanceFromGroup(MaxY,north,DistanceFromGroup) and DistanceFromGroup > MaxDistanceFromGroup) then
		{
			print( leavingthegroup(north));
			@competition( noMove(), _ );
			Moved()
		}
		else
		{
			print( goingToMove( north ) );
			@competition( moveTo( X,Y, north ), _ );
			Moved()	
		}
	}
	
	move( east ) <- phase( move ) and position(X,Y) and maxDistanceFromGroup(MaxDistanceFromGroup)|
	{
		
		@competition(getMaxXOfTeamMates(), ActionResult );
		B( ActionResult = [actionresult( [MaxX] )]);
		
			print(maxX(MaxX));
		
		//Y+1 - MaxY is the disance from the group
		if B(MaxX > 0  and distanceFromGroup(MaxX,east,DistanceFromGroup) and DistanceFromGroup > MaxDistanceFromGroup) then
		{
			print( leavingthegroup(east));
			@competition( noMove(), _ );
			Moved()
		}
		else
		{
			print( goingToMove( east ) );
			@competition( moveTo( X,Y, east ), _ );
			Moved()	
		}
	}
	
	move( south ) <- phase( move ) and position(X,Y) and maxDistanceFromGroup(MaxDistanceFromGroup)|
	{
		
		@competition(getMaxYOfTeamMates(), ActionResult );
		B( ActionResult = [actionresult( [MinY] )]);
		
		print(minY(MinY));
		
		//Y+1 - MaxY is the disance from the group
		if B(MinY > 0 and distanceFromGroup(MinY,south,DistanceFromGroup) and DistanceFromGroup > MaxDistanceFromGroup) then
		{
			print( leavingthegroup(south));
			@competition( noMove(), _ );
			Moved()
		}
		else
		{
			print( goingToMove( south ) );
			@competition( moveTo( X,Y, south ), _ );
			Moved()	
		}
	}
	
	move( west ) <- phase( move ) and position(X,Y) and maxDistanceFromGroup(MaxDistanceFromGroup)|
	{
		
		@competition(getMaxYOfTeamMates(), ActionResult );
		B( ActionResult = [actionresult( [MinX] )]);
		
		print(minX(MinX));
		
		//Y+1 - MaxY is the disance from the group
		if B(MinX > 0 and distanceFromGroup(MinX,west,DistanceFromGroup) and DistanceFromGroup > MaxDistanceFromGroup) then
		{
			print( leavingthegroup(west));
			@competition( noMove(), _ );
			Moved()
		}
		else
		{
			print( goingToMove( west ) );
			@competition( moveTo( X,Y, west ), _ );
			Moved()	
		}
	}
	
	
	
	noMove() <- phase(move ) |
	{
		@competition( noMove(), _ );
		Moved()
	}
	
	
	// Move to a specific coordinate
	moveTo(X,Y) <-	phase(move)  and position(Xnow,Ynow) and width(Width) and height(Height) 
					 |
	{
		print( moveTo___(X,Y) );
		if B( X > Xnow and X < Width) then { move( east ) } else{ 
			if B( X < Xnow and (X = 0 or X > 0 ) ) then { move( west ) } else{ 
				if B( Y < Ynow and (Y = 0 or Y > 0 ) ) then { move( south ) } else{ 
					if B( Y > Ynow and Y < Height ) then { move( north ) } else{ 
						noMove() } } } 
		};
		skip
	}
	
	// No weakestEnemies, so walk random
	walkToWeakest([] ) <- phase(move) and round(Round) and moveOpositePlacementRounds(R) and placement(Placement)|
	{	
		print( walkToWeakerstRandon ); 
		if B(Round < R) then
		{
			if B(Placement = north) then
			{
				move(south)
			}
			else
			{	
				if B(Placement = east) then
				{
					move(west)
				}
				else
				{
					if B(Placement = south) then
					{
						move(north)
					}
					else
					{
						move(east)
					}
				}
			}
		}
		else
		{
			randomMove()
		}
	}
			
	// Weakest enemy is not in shootRange yet, so walk to it
	walkToWeakest([[X, Y, TargetName, TargetTeam, TargetBodyType, HP] | Rest]) <- phase(move) and position(Xself, Yself) and
		not inShootRange( X, Y ) |
	{	
		print( walkToWeakest(X, Y, Xself, Yself, TargetName, HP ) );
	moveTo( X, Y )	}
	
	// Weakest enemy is in shootRange, so noMove
	walkToWeakest([[X, Y, TargetName, TargetTeam, TargetBodyType, HP] | Rest]) <- phase(move) and position(Xself, Yself) and
		inShootRange( X, Y ) |
	{	print( walkToWeakestInRange(X, Y, Xself, Yself, TargetName, HP ) );	noMove()	
		// TO Make: walk away from most dangerous enemy?
		} 
	
	
	
	
	/* Informs teammembers in range about the target you wish to shoot. */
	informShootPlan(TeamMembers, EnemiesInShootRange) <- phase(shoot) and bodyType(BodyType)|
	{
		//The best target is alwyas the head of the list, so inform others your wish to shoot this target.
		//This is because the list is sorted at bestTarget order. If the list is empty there is no need to inform.
		if B(EnemiesInShootRange = [[X,Y,Name,Team,TargetBodyType,HP] | _]) then 
		{
			B(getDamage(TargetBodyType,Damage));
			sendShootPlan(TeamMembers,X,Y,Damage, Name, Team, TargetBodyType)
		}
	}
	
	/* Sends message to teammembers with the target you wish to shoot*/
	/* for some strange reason  sendShootPlan([[_,_,Name,_,_,_]|Rest] does NOT match, so dont use underscores*/
	sendShootPlan([],X,Y,Damage, Name, Team, Type) <- true | {skip}
	sendShootPlan([[A,B,Name,Team,Type,HP]|Rest], X, Y, Damage, TargetName, TargetTeam, TargetType) <- rank(Rank) and phase(shoot) |
	{
		send(Name,inform,informShootPlan(X,Y,Rank,Damage, TargetName, TargetTeam, TargetType));
		sendShootPlan(Rest,X,Y,Damage, TargetName, TargetTeam, TargetType)
	}
	
	
	/* Iterates over the target list, and determines if the agent is gonna shoot the target.
	 * If informShootPlan messages of other agents with a lower rank are received for the same target, 
	 * that allready killed the agent, the agent then goes to the next target in the list.
	 */ 
	determineShot([]) <- phase(shoot)| 
	{ 
		@competition(noShoot(),_);
		NoShot()
	}
	determineShot([[X,Y,TargetName,TargetTeam,TargetBodyType,HP] | Rest]) <- phase(shoot) and rank(Rank) 
		and bodyType(BodyType) 
		and	findall(shot(RankThem,Dmg, TargetName, TargetTeam, TargetType),informShootPlanReceived(TeamMate,X,Y,RankThem,Dmg, TargetName, TargetTeam, TargetType),Shots)|
	{
		/* Retrieve the total damage from the shots wishes received 
		on that target from agents with rank lower than yours*/
		B(getTotalDamage(Shots,Rank,TotalDamage));
		
		/* If the totalDamage is greater or equal to the expected HP of that target, shoot an other target*/
		if B(TotalDamage >= HP) then
		{
			// 
			determineShot(Rest)
		}
		else
		{
			/* environment action: Shoot the target at position (x,y)*/
			@competition(shoot(X,Y),_);
			Shot(X,Y,TargetName,TargetTeam,TargetBodyType)
		}
		
		//@competition( registerShot( X, Y, TotalDamage, TargetName, TargetTeam, TargetBodyType ), _)
	}
		
	
	/* Informs other teammates within sense range about the shot fired*/
	sendShot([],X,Y,Damage, TargetName, TargetTeam, TargetBodyType) <- true | {skip}
	sendShot([[A,B,Name,Team,Type,HP]|Rest],X,Y,Damage, TargetName, TargetTeam, TargetBodyType) <- true |
	{
	 	send(Name,inform,informShot(X,Y,Damage, TargetName, TargetTeam, TargetBodyType));
	 	sendShot(Rest,X,Y,Damage, TargetName, TargetTeam, TargetBodyType)
	}
		
	/* Removes shooting beliefs that are not needed anymore */
	removeShotInfo() <- true |
	{
		/* Too slow
		while B( informShootPlanReceived(TeamMate,X,Y,Rank,Damage) ) do
		{
			RemoveShootPlanMessage( TeamMate,X,Y,Rank,Damage )
		};
		*/
		while B(shot(X,Y,TargetName,TargetTeam,TargetBodyType) ) do
		{
			RemoveShot(X,Y,TargetName,TargetTeam,TargetBodyType)
		}
	}
	
	
	wait(0) <- true | skip
	wait(Times) <- true |
	{
		wait(Times-1)
	}
	
	//activationMessage
	message( Manager,inform, _, _, activate( X, Y, BodyType,Rank ) ) <- managerAgent(Manager) and phase(waitForActivation) |
	{
		ActivatedMessageReceived(X,Y,BodyType,Rank)
	}
	
	//informshootPlan message
	message(TeamMate,inform,_,_,informShootPlan(X,Y,Rank,Damage, TargetName, TargetTeam, TargetType) ) <- round(Round)|
	{
		InformShootPlanReceived(Round,TeamMate,X,Y,Rank,Damage, TargetName, TargetTeam, TargetType)
	}
	
	// Teammate shot someone
	message(TeamMate,inform,_,_,informShot(X,Y,Damage, TargetName, TargetTeam, TargetBodyType) ) <- true |
	{
		@competition(registerShot(X,Y,Damage, TargetName, TargetTeam, TargetBodyType),_)
	}
	
	
	event( sensed(State, X,Y,SensedAgents),competition) <- true|
	{
		print( sensed____(State,X,Y,SensedAgents ) );
		Sensed(State,X,Y)
	}
	
	event(died(_),competition) <- true |
	{
		Died();
		print(iamDead)
	}
	
	event(gamestarted(_),competition) <- true |
	{
		GameStarted();
		skip
	}
	
	event( X, _) <- true |
	{
		print(event(X))
	}
	
	
	
	
	
	//Not used:
	
	/* 
	informShootPlan() <- phase(shoot) and rank(Rank) and bodyType(BodyType)|
	{
		@competition(getTeamMembers(),ActionResult1);
		B( ActionResult1 = [actionresult( TeamMembers)]);
		
		@competition(getEnemiesInShootingRange(),ActionResult2);
		if B( ActionResult2 = [actionresult( [[X,Y,Name,Team,TargetBodyType,HP] | _] )] ) then
		{
		
			print(planningToShoot(X,Y));
			
			InformShootPlanSend(TeamMembers);
		
			if B( (BodyType=rock and TargetBodyType=scissor) 
			or (BodyType=paper and TargetBodyType=rock) 
			or (BodyType=scissor and TargetBodyType=paper)) then
			{
				informShootPlan(TeamMembers,X,Y,Rank,3)
			}
			else
			{
				informShootPlan(TeamMembers,X,Y,Rank,1)
			}
		}
	}
	*/
	
	/*
	informShot(X,Y,TargetName, TargetTeam,TargetBodyType) <- phase(shoot) and state(alive)|
	{
		
		B(getDamage(TargetBodyType,Damage));
		@competition(getTeamMembers(),ActionResult);
		B( ActionResult = [actionresult( TeamMembers)]);
		
		print(informShot(begin,TeamMembers,Damage));
		informShot(TeamMembers,X,Y,Damage, TargetName, TargetTeam, TargetBodyType)
	}
	 */
	
	/*
	true <- phase(informShootPlan) and position(X,Y) and bodyType(BodyType) |
	{
		informShootPlan();
	
		wait(3);
		B(findall(TeamMember,informShootPlanReceived(TeamMember,_,_,_,_),TeamMembers));
		print(allInformShootPlanReceived(TeamMembers));
		InformedShoot()
	}
	*/
	
	/* 
	true  <- phase(shoot) and state(alive) and position(X,Y) and bodyType(BodyType) and width(Width) and height(Height) and placement(Placement)|
	{
		shoot();
		removeShotInfo();
		Shooted()
	}
	*/
	
	/*
	shootTargets([]) <- phase(shoot) and state(alive) | 
	{ 
		@competition(noShoot(),_)
	}
	shootTargets([[X,Y,TargetName,TargetTeam,TargetBodyType,HP] | Rest]) <- phase(shoot) and state(alive) and rank(Rank) and 
						bodyType(BodyType) and 
						findall(shot(RankThem,Damage),informShootPlanReceived(TeamMate,X,Y,RankThem,Damage),Shots) |
	{
		print(shoot(Shots,Rank));
		B(getTotalDamage(Shots,Rank,TotalDamage));
		print(totalDamage(TotalDamage,HP));
		if B(TotalDamage >= HP) then
		{
			// already dead
			print(recursiveShootCall(Rest));
			shootTargets(Rest)
		}
		else
		{
			// not dead, so shoot
			@competition(shoot(X,Y),_);
			if B( (BodyType=rock and TargetBodyType=scissor) 
				or (BodyType=paper and TargetBodyType=rock) 
				or (BodyType=scissor and TargetBodyType=paper)) then
			{
				print( shotOnWith(X,Y,3) );
				informShot(X,Y,3, TargetName, TargetTeam, TargetBodyType )
			}
			else
			{
				print( shotOnWith(X,Y,1) );
				informShot(X,Y,1, TargetName, TargetTeam, TargetBodyType )
			}
			
		}
	}
	*/
	
	 